/// @tags: LCA ReversionEdge
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <vector>

typedef long long ll;

int const N = 2e5 + 5;

template <typename T>
inline T &read(T &x) {
  x = 0;
  bool f = false;
  short ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') f = true;
    ch = getchar();
  }
  while (isdigit(ch)) x = x * 10 + (ch ^ '0'), ch = getchar();
  if (f) x = -x;
  return x;
}

int n, m;
int fa[N], dep[N], cx[N], cy[N], tmp[N], cnt;
bool vis[N], ins[N];
std::vector<int> G[N];

inline int getLCA(int x, int y) {
  while (dep[x] > dep[y]) x = fa[x];
  while (dep[y] > dep[x]) y = fa[y];
  while (x != y) x = fa[x], y = fa[y];
  return x;
}

inline void print() {
  printf("%d", cnt);
  for (int i = 1; i <= cnt; i++) printf(" %d", tmp[i]);
  puts("");
  cnt = 0;
}

inline void addPath(int x, int y) {
  while (x != y) {
    tmp[++cnt] = x;
    x = fa[x];
  }
  tmp[++cnt] = y;
}

inline void print(int a, int b, int c, int d) {
  if (dep[b] > dep[d]) {
    std::swap(a, c);
    std::swap(b, d);
  }
  int lca = getLCA(a, c);
  puts("YES");
  addPath(lca, d);
  std::reverse(tmp + 1, tmp + cnt + 1);
  print();
  addPath(d, b);
  addPath(a, lca);
  print();
  tmp[++cnt] = d;
  addPath(c, lca);
  print();
  return;
}

bool dfs(int u) {
  dep[u] = dep[fa[u]] + 1;
  vis[u] = ins[u] = true;
  for (auto &v : G[u])
    if (v != fa[u]) {
      if (!vis[v]) {
        fa[v] = u;
        if (dfs(v)) return true;
      } else if (ins[v]) {
        for (int x = u; x != v; x = fa[x])
          if (cx[x] && cy[x]) return print(cx[x], cy[x], u, v), true;
          else
            cx[x] = u, cy[x] = v;
      }
    }
  ins[u] = false;
  return false;
}

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("/tmp/CodeTmp/testdata.in", "r", stdin);
  freopen("/tmp/CodeTmp/testdata.out", "w", stdout);
#else
  freopen("CF521E Cycling City.in", "r", stdin);
  freopen("CF521E Cycling City.out", "w", stdout);
#endif
#endif

  read(n), read(m);
  for (int i = 1, u, v; i <= m; i++) {
    read(u), read(v);
    G[u].push_back(v);
    G[v].push_back(u);
  }
  for (int i = 1; i <= n; i++)
    if (!vis[i])
      if (dfs(i)) return 0;
  puts("NO");
  return 0;
}